using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.WowAddonStudio.FrameXml.Design.Support.NameCreationService;

namespace Microsoft.WowAddonStudio.FrameXml.Design.Services.NameCreationService
{
	/// <summary>
	/// 
	/// </summary>
	public abstract class UniqueNumberGeneratorBase : IUniqueNumberGenerator
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="UniqueNumberGeneratorBase"/> class.
		/// </summary>
		/// <param name="componentContainer">The component container.</param>
		protected UniqueNumberGeneratorBase(IContainer componentContainer)
		{
			ComponentContainer = componentContainer;
		}

		/// <summary>
		/// Gets or sets the component container.
		/// </summary>
		/// <value>The component container.</value>
		protected IContainer ComponentContainer { get; private set; }

		#region IUniqueNumberGenerator Members

		/// <summary>
		/// Generates the unique number.
		/// </summary>
		/// <param name="prefixName">Name of the prefix.</param>
		/// <returns></returns>
		public abstract int GenerateUniqueNumber(string prefixName);

		#endregion


		/// <summary>
		/// Gets the numeric chars.
		/// </summary>
		/// <param name="text">The text.</param>
		/// <returns></returns>
		public static int GetNumericChars(string text)
		{
			int result = 1;
			if (!string.IsNullOrEmpty(text))
			{
				var builder = new StringBuilder(text.Length);
				foreach (char chr in text)
				{
					if (Char.IsDigit(chr))
						builder.Append(chr);
					else
						break;
				}
				string textNum = builder.ToString();
				if (textNum.Length > 0)
					int.TryParse(builder.ToString(), out result);
				else
					result = 1;
			}
			return result;
		}

        /// <summary>
        /// Gets the components.
        /// </summary>
        /// <param name="prefixName">Name of the prefix.</param>
        /// <returns></returns>
        public List<Component> GetComponents(string prefixName)
		{
			var result = new List<Component>();
            var subResult = new List<Component>();

			result.AddRange(
                ComponentContainer.Components.OfType<Component>()
					.Where(ctrl => ctrl.Site.Name.StartsWith(prefixName, StringComparison.OrdinalIgnoreCase)));

            foreach (Component component in result)
			{
                if(component is Control)
                    subResult.AddRange(GetControls(component as Control, prefixName));
                else
                    subResult.Add(component);
			}

			result.AddRange(subResult);
			return result;
		}
        
		/// <summary>
		/// Gets the controls recursively.
		/// </summary>
		/// <returns></returns>
		private List<Component> GetControls(Control control, string prefixName)
		{
            var result = new List<Component>();
            var subResult = new List<Component>();

			result.AddRange(
                control.Controls.OfType<Component>()
					.Where(ctrl => ctrl.Site.Name.StartsWith(prefixName, StringComparison.OrdinalIgnoreCase)));
			
            foreach (Control ctrl in result)
			{
                subResult.AddRange(GetControls(ctrl, prefixName));
			}

			result.AddRange(subResult);
			return result;
		}
	}
}